package mobi.greenplate.client.parser;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 *
 * @author dmakariev
 */
public abstract class DomainHandler<T> extends DefaultHandler {

    public abstract T getEntity();

    public abstract void endTag(String parentPath, String tagName, String text);

    public abstract void startTag(String parentPath, String tagName);
    private final StringBuilder stringBuilder = new StringBuilder();
    private String parentPath = "/";

    @Override
    public final void endElement(String uri, String localName, String qName) throws SAXException {
        final String tagName = chooseTagName(localName,qName);
        final String text = consumeText();
        removeLastChild();

        endTag(getParentPath(), tagName, text);
    }
    
    private static String chooseTagName(String localName, String qName){
    	if(null==qName||"".equals(qName)){
    		return localName;
    	}
    	return qName;
    }

    @Override
    public final void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        final String tagName = chooseTagName(localName,qName);

        startTag(parentPath, tagName);

        stringBuilder.setLength(0);
        addChildTag(tagName);
    }

    @Override
    public final void characters(char[] ch, int start, int length) throws SAXException {
        stringBuilder.append(ch, start, length);
    }

    private String consumeText() {
        final String text = stringBuilder.toString();
        stringBuilder.setLength(0);
        return text;
    }

    private void addChildTag(String tagName) {
        parentPath += "/" + tagName;
    }

    private void removeLastChild() {
        final int slashIndex = parentPath.lastIndexOf("/");
        final boolean isOnlyParent = (0 == slashIndex);
        if (false == isOnlyParent) {
            parentPath = parentPath.substring(0, slashIndex);
        }
    }

    private String getParentPath() {
        return parentPath;
    }
}
